home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_mac.hqx / SRGP port to 5.0 (compressed) / SRGP_SPHIGS Root / MacSPHIGS / sph_view.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-13  |  13.2 KB  |  506 lines

  1. #include "HEADERS.h"
  2. #include "sphigslocal.h"
  3. #include <stdio.h>
  4.  
  5. #define THE_VIEW    SPH_viewTable[viewIndex]
  6.  
  7. #define FEPS         (1e-12)
  8. #define FZERO(N)      ((N) < FEPS && (N) > -FEPS)
  9. #define FEQUAL(A,B)      (((A) - (B)) < FEPS && ((A) - (B)) > -FEPS)
  10.  
  11. #define PI            3.1415926535
  12.  
  13. #include "sph_view.proto.h"
  14.  
  15.  
  16.  
  17. /*!*/
  18. void 
  19. SPH_evaluateViewOrientationMatrix 
  20.    (point view_ref_point,
  21.     vector view_plane_normal, vector view_up_vector,
  22.     matrix vo_matrix /*varparm*/ )
  23. {
  24.    vector tempvec, up_v, normal_v, proj_up_v, right_v;
  25.    matrix trans, rot;
  26.    double dot, tmp1;
  27.  
  28.  
  29.    /* FIND THE UNIT VERSION OF THE up VECTOR */
  30.    MAT3_COPY_VEC(up_v, view_up_vector);
  31.    MAT3_NORMALIZE_VEC(up_v, tmp1);
  32.    if (tmp1 == 0.0)
  33.       SPH__error (ERR_MAT3_PACKAGE, "up vector has zero length");
  34.  
  35.    /* FIND THE UNIT VERSION OF THE view plane normal VECTOR */
  36.    MAT3_COPY_VEC(normal_v, view_plane_normal);
  37.    MAT3_NORMALIZE_VEC(normal_v, tmp1);
  38.    if (tmp1 == 0.0)
  39.       SPH__error (ERR_MAT3_PACKAGE, "View plane normal has zero length");
  40.  
  41.    /* Find the projection of the up vector on the film plane */
  42.    dot = MAT3_DOT_PRODUCT(up_v, normal_v);
  43.    if (dot == 1.0 || dot == -1.0)
  44.       SPH__error (ERR_MAT3_PACKAGE, "Up vector and view plane normal are the same");
  45.  
  46.    MAT3_LINEAR_COMB(proj_up_v, 1.0, up_v, -dot, normal_v);
  47.    MAT3_NORMALIZE_VEC(proj_up_v, tmp1);
  48.  
  49.    /* Find the vector that goes to the right on the film plane */
  50.    MAT3cross_product(right_v,    normal_v, proj_up_v);
  51.  
  52.  
  53. /*!*/
  54.    /********* STEP 1 OF FOLEY CHAPTER VIEW.5.2 */
  55.    /* Translate view reference point to origin */
  56.    MAT3_SCALE_VEC(tempvec, view_ref_point, -1);
  57.    MAT3translate(trans, tempvec);
  58.  
  59.  
  60.    /********* STEP 2 OF FOLEY CHAPTER VIEW.5.2 */
  61.    /* Rotate so normal lies on z-axis and proj_up is on y-axis */
  62.    /* Remember: right-hand rule is in effect. */
  63.    MAT3identity(rot);
  64.    rot[0][2] = normal_v[X];
  65.    rot[1][2] = normal_v[Y];
  66.    rot[2][2] = normal_v[Z];
  67.  
  68.    rot[0][0] = -right_v[X];
  69.    rot[1][0] = -right_v[Y];
  70.    rot[2][0] = -right_v[Z];
  71.  
  72.    rot[0][1] = proj_up_v[X];
  73.    rot[1][1] = proj_up_v[Y];
  74.    rot[2][1] = proj_up_v[Z];
  75.  
  76.  
  77.    /*************** PRODUCE THE FINAL PRODUCT: TRANS x ROT */
  78.    MAT3mult(vo_matrix,   trans, rot);
  79. }
  80.  
  81.  
  82.  
  83.  
  84. /*!*/
  85.  
  86.  
  87. static double most_recent_F, most_recent_B;
  88.  
  89.  
  90.  
  91. void
  92. SPH_evaluateViewMappingMatrix
  93.    (double umin, double umax, double vmin, double vmax,
  94.     int proj_type,  /* ORTHOGRAPHIC or PERSPECTIVE */
  95.     point proj_ref_point,
  96.     double front_plane_dist, double back_plane_dist,
  97.     double viewport_minx, 
  98.     double viewport_maxx, 
  99.     double viewport_miny, 
  100.     double viewport_maxy,
  101.     double viewport_minz, 
  102.     double viewport_maxz,
  103.     matrix vm_matrix /*varparm*/ )
  104. {
  105.    matrix step3_matrix, step4_matrix, step3and4_matrix, step5_matrix,
  106.           step6_matrix, sklar_matrix;
  107.    MAT3hvec vrp;
  108.  
  109.    MAT3_SET_HVEC (vrp, 0.0, 0.0, 0.0, 1.0);
  110.  
  111. /*!*/
  112.  
  113.    /**** First, we test for "garbage in" ****/
  114.    if (proj_ref_point[Z] <= 0.0)
  115.       SPH__error (ERR_BAD_VIEWING_PARAMETER, 
  116.           "proj_ref_point[Z] is zero or negative\n");
  117.    if (front_plane_dist >= proj_ref_point[Z])
  118.       SPH__error (ERR_BAD_VIEWING_PARAMETER, 
  119.          "front clip plane lies behind or on the PRP\n");
  120.    if (back_plane_dist >= front_plane_dist)
  121.       SPH__error (ERR_BAD_VIEWING_PARAMETER, 
  122.          "back clip plane is closer to PRP than the front clip plane");
  123.  
  124.  
  125.    /**** Save the F and B because currently there's a bug in ORTHO mode;
  126.          we can't backcalc the F and B from the vm matrix in ORTH mode! ***/
  127.    if (proj_type == ORTHOGRAPHIC) {
  128.       most_recent_F = front_plane_dist;
  129.       most_recent_B = back_plane_dist;
  130.    }
  131.  
  132.    /********* STEP 3 OF FOLEY CHAPTER VIEW.5.2 */
  133.    /* Only to be done for PERSPECTIVE. */
  134.    /* Translate so the PRP (center of projection) is at the origin. */
  135.    if (proj_type == PERSPECTIVE) {
  136.       vector tempvec;
  137.  
  138.       MAT3_SCALE_VEC(tempvec, proj_ref_point, -1);
  139.       MAT3translate(step3_matrix, tempvec);
  140. #ifdef DEBUG
  141.       MAT3print_formatted
  142.      (step3_matrix, stdout, 0, "Foley step 3  ", 0, 0); 
  143. #endif
  144.       
  145.       /* update vrp */
  146.       MAT3_ADD_VEC(vrp,  vrp, tempvec);
  147.    }
  148.    else
  149.       MAT3identity (step3_matrix);
  150.  
  151.  
  152.  
  153. /*!*/   
  154.    /********* STEP 4 OF FOLEY CHAPTER VIEW.5.2 */
  155.    /* Shear so that the center line of the view volume lies on z-axis */
  156.    {
  157.       vector dop_v;   /* direction of projection */
  158.  
  159.       if (proj_type == PERSPECTIVE) {
  160.      dop_v[0] = vrp[0] + (umax+umin)/2;
  161.      dop_v[1] = vrp[1] + (vmax+vmin)/2;
  162.      dop_v[2] = vrp[2];
  163.       }
  164.       else {
  165.      dop_v[0] = (umax+umin)/2 - proj_ref_point[0];
  166.      dop_v[1] = (vmax+vmin)/2 - proj_ref_point[1];
  167.      dop_v[2] = 0.0 - proj_ref_point[2];
  168.       }
  169.  
  170.       MAT3shear(step4_matrix, -dop_v[X] / dop_v[Z], -dop_v[Y] / dop_v[Z]);
  171. #ifdef DEBUG
  172.       MAT3print_formatted
  173.         (step4_matrix, stdout, 0, "Shear  ", 0, 0); 
  174. #endif
  175.    }
  176.  
  177.  
  178.  
  179.    
  180.  
  181. /*!*/   
  182.    /* LET'S COMPUTE THE INTERMEDIATE RESULT: step3 times step4 */
  183.    MAT3mult (step3and4_matrix, step3_matrix, step4_matrix);
  184. #ifdef DEBUG
  185.    MAT3print_formatted
  186.       (step3and4_matrix, stdout, 0, "Foley step 3 x step 4  ", 0, 0); 
  187. #endif
  188.  
  189.  
  190. /*!*/
  191.    /* STEPS 5 and 6 DIFFER BETWEEN THE TWO TYPES OF PROJECTIONS. */
  192.  
  193.    if (proj_type == ORTHOGRAPHIC) {
  194.       vector tempvec;
  195.       MAT3_SET_VEC (tempvec,  
  196.             (umax+umin)/(-2.0),
  197.             (vmax+vmin)/(-2.0),
  198.             0.0);            /******** F=0.0 */
  199.       MAT3translate(step5_matrix, tempvec);
  200. #ifdef DEBUG
  201.       MAT3print_formatted
  202.         (step5_matrix, stdout, 0, "ORTHO step Tpar w/ F=0  ", 0, 0); 
  203. #endif
  204.  
  205.       MAT3_SET_VEC (tempvec,  
  206.             2.0/(umax-umin),
  207.             2.0/(vmax-vmin),
  208.             1.0/2.0);            /******** B=2.0 */
  209.       MAT3scale(step6_matrix, tempvec);
  210. #ifdef DEBUG
  211.       MAT3print_formatted
  212.         (step6_matrix, stdout, 0, "ORTHO step Spar w/ B=2  ", 0, 0); 
  213. #endif
  214.    }
  215.    else {
  216. /*!*/   
  217.    /********* STEP 5 OF FOLEY CHAPTER VIEW.5.2 */
  218.    /* Get it to canonical perspective volume. */
  219.       MAT3hvec vrp_prime;
  220.       vector scale_vec;
  221.       double zmin;
  222.  
  223.       /* FIRST, find VRP' (VRP after steps 3 and 4) */
  224.       MAT3mult_hvec (vrp_prime, vrp, step4_matrix, FALSE);
  225. #ifdef DEBUG
  226.       printf ("vrp_prime is found to be: (%f %f %f %f)\n",
  227.           vrp_prime[0], vrp_prime[1], vrp_prime[2], vrp_prime[3]);
  228. #endif
  229.  
  230.       /* Compute a scale matrix ala Foley */
  231. #     define F front_plane_dist
  232. #     define B back_plane_dist
  233.       MAT3_SET_VEC(scale_vec,
  234.            (2.0)*vrp_prime[Z]/((umax-umin)*(vrp_prime[Z]+B)),
  235.            (2.0)*vrp_prime[Z]/((vmax-vmin)*(vrp_prime[Z]+B)),
  236.            1.0/(vrp_prime[Z]+B));
  237.  
  238.       MAT3scale(step5_matrix, scale_vec);
  239. #ifdef DEBUG
  240.       MAT3print_formatted
  241.         (step5_matrix, stdout, 0, "Foley step 5 w/ B=2  ", 0, 0); 
  242. #endif
  243.  
  244. /*!*/
  245.    /************ STEP 6 OF FOLEY */
  246.    /* Get it to canonical parallel volume. */
  247.    
  248.    
  249.       zmin = (vrp_prime[Z]+F)/(vrp_prime[Z]+B);
  250. #ifdef DEBUG
  251.       fprintf (stderr, "VIEW MAPPING MATRIX CALC'D FOR    F=%f  B=%f\n", F,B);
  252.       fprintf (stderr, "zmin is calculated as %f\n", zmin);
  253. #endif
  254.       MAT3zero (step6_matrix);
  255.       step6_matrix[0][0] = 1.0;
  256.       step6_matrix[1][1] = 1.0;
  257.       step6_matrix[2][2] = 1.0 / (1.0 - zmin);
  258.       step6_matrix[3][2] = (0.0 - zmin) / (1.0 - zmin);
  259.       step6_matrix[2][3] = 1.0;
  260. #ifdef DEBUG
  261.       MAT3print_formatted
  262.         (step6_matrix, stdout, 0, "Foley step 6 w/ F=0  ", 0, 0); 
  263. #endif
  264.    }
  265.  
  266.   
  267. /*!*/   
  268.    /******** DO SOME MERGING */
  269.    MAT3mult(vm_matrix,   step3and4_matrix, step5_matrix);
  270.    MAT3mult(vm_matrix,   vm_matrix, step6_matrix);
  271. #ifdef DEBUG
  272.    MAT3print_formatted
  273.          (vm_matrix, stdout, 0, "All of Foley's steps  ", 0, 0); 
  274. #endif
  275.  
  276.  
  277. /*!*/
  278.    /********* SKLAR'S STEP */
  279.    /* To bring the canonical (-1 to +1) to the NPC viewport.
  280.     * This transformation will produce NDC coordinates (if you ignore z).
  281.     */
  282.    {
  283.       matrix scalemat, transmat;
  284.       vector scale_vec, trans_vec;
  285.  
  286.       MAT3_SET_VEC(scale_vec,
  287.            (viewport_maxx - viewport_minx)/2,
  288.            (viewport_maxy - viewport_miny)/2,
  289.            1.0);
  290.       MAT3scale(scalemat,   scale_vec);
  291.       MAT3_SET_VEC(trans_vec,
  292.            (viewport_minx+viewport_maxx)/2,
  293.            (viewport_miny+viewport_maxy)/2,
  294.            0);
  295.       MAT3translate(transmat,   trans_vec);
  296.  
  297.       MAT3mult(sklar_matrix,   scalemat, transmat);
  298.    }
  299.  
  300.    MAT3mult(vm_matrix,   vm_matrix, sklar_matrix);
  301.    
  302. #ifdef DEBUG
  303.    MAT3print_formatted
  304.          (vm_matrix, stdout, 0, "Final matrix  ", 0, 0); 
  305. #endif
  306. }
  307.  
  308.  
  309.  
  310.  
  311.  
  312. /** SPH_translateWCtoPDC
  313. Translates a single point.
  314. **/
  315. void
  316. SPH__translateWCtoPDC (int viewIndex, MAT3hvec inpt, MAT3hvec outpt)
  317. {
  318.    MAT3mult_hvec (outpt, inpt, THE_VIEW.cammat, TRUE);
  319. }
  320.  
  321.  
  322.  
  323. /** SPH_translateMCtoPDC
  324. Translates a single point from MC to PDC by 
  325. multiplying by the TOTAL transform matrix.
  326. **/
  327. void
  328. SPH__translateMCtoPDC (matrix xformmat, MAT3hvec inpt, MAT3hvec outpt)
  329. {
  330.    MAT3mult_hvec (outpt, inpt, xformmat, TRUE);
  331. }
  332.  
  333.  
  334.  
  335.  
  336.  
  337. /** SPH_update_view_info
  338. Upon entry, the vo_matrix, vm_matrix, and viewport for the given view can
  339. be assumed correct, but the pdc-viewport and the final viewing matrix
  340. are obsolete and must be recomputed.
  341. **/
  342.  
  343. void SPH__updateViewInfo (int viewIndex)
  344. {
  345.    vector scale_vec;
  346.    matrix scale_mat;
  347.  
  348.  
  349.    THE_VIEW.pdc_viewport.bottom_left.x =
  350.        THE_VIEW.viewport.bottom_left.x * SPH_ndcSpaceSizeInPixels;
  351.    THE_VIEW.pdc_viewport.bottom_left.y =
  352.        THE_VIEW.viewport.bottom_left.y * SPH_ndcSpaceSizeInPixels;
  353.    THE_VIEW.pdc_viewport.top_right.x =
  354.       (THE_VIEW.viewport.top_right.x * SPH_ndcSpaceSizeInPixels) - 1;
  355.    THE_VIEW.pdc_viewport.top_right.y =
  356.       (THE_VIEW.viewport.top_right.y * SPH_ndcSpaceSizeInPixels) - 1;
  357.  
  358.    /* ONE FINAL STEP.  The transformation after the view-orientation
  359.       and the view-mapping produces NDC coords (NPC, to PHIGS-gurus).
  360.       We need to scale that by the pixel-size of our NDC space to
  361.       get PDCs.
  362.       The Z-coord of the PDC coord is being scaled quite substantially
  363.          so when we turn it into an integer via truncation it doesn't
  364.      lose its meaning.  It will be used for HLHSR.
  365.     */
  366.    MAT3mult (THE_VIEW.cammat, THE_VIEW.vo_matrix, THE_VIEW.vm_matrix);
  367.    MAT3_SET_VEC(scale_vec,  
  368.         SPH_ndcSpaceSizeInPixels*1.0,
  369.         SPH_ndcSpaceSizeInPixels*1.0,
  370.         1000.0);
  371.    MAT3scale (scale_mat, scale_vec);
  372.    MAT3mult (THE_VIEW.cammat,    THE_VIEW.cammat, scale_mat);
  373. }
  374.  
  375.    
  376.  
  377.  
  378. /** SPH_init_view_table
  379. **/
  380. void SPH__init_view_table (void)
  381. {
  382.    register viewIndex=0;
  383.    register view_spec *v;
  384.    point vrp, prp;
  385.    vector vpn, vupv;
  386.    matrix vo_matrix, vm_matrix;
  387.  
  388.    SPH_evaluateViewOrientationMatrix 
  389.       (SPH_defPoint(vrp,  0.0,0.0,0.0),
  390.        SPH_defPoint(vpn,  0.0,0.0,1.0),
  391.        SPH_defPoint(vupv, 0.0,1.0,0.0),
  392.        vo_matrix);
  393.  
  394.    SPH_evaluateViewMappingMatrix
  395.       (0.0,1.0,  0.0,1.0,
  396.        ORTHOGRAPHIC,
  397.        SPH_defPoint(prp,  0.5,0.5,1.0),
  398.        0.99, -50000.0,
  399.        0.0,1.0, 0.0,1.0, 0.0, 1.0,
  400.        vm_matrix);
  401.  
  402.    bzero (SPH_viewTable, sizeof(view_spec)*(MAX_VIEW_INDEX+1));
  403.  
  404. #if defined(THINK_C) || defined(__MSDOS__)
  405. #define HUGE ((double)9999999.0)
  406. #endif
  407.    v = SPH_viewTable;
  408.    for (viewIndex=0; viewIndex<=MAX_VIEW_INDEX; viewIndex++) {
  409.       SPH_setViewRepresentation
  410.      (viewIndex,
  411.       vo_matrix, vm_matrix,
  412.       0.0,1.0, 0.0,1.0, 0.0,1.0);
  413.       ClearBitstring (&v->descendent_list);
  414.       v->rendermode = WIREFRAME;
  415.       v->background_color = SRGP_WHITE;
  416.       MAT3_SET_VEC (v->uvn_point_light_source, 0.0, HUGE, HUGE);
  417.       v++;
  418.    }
  419. }
  420.  
  421.  
  422.  
  423. /** SPH_setViewBackgroundColor
  424. On a per-view basis, the background color can be set. 
  425. Warning: this does NOT cause a refresh.  The new color will only
  426.    be seen upon the next operation causing a refresh.
  427. **/
  428.  
  429. void SPH_setViewBackgroundColor (int viewIndex, int color)
  430. {
  431.    if ( ! IS_LEGAL_COLOR_INDEX(color))
  432.       color = 0;
  433.    SPH_viewTable[viewIndex].background_color = color;
  434. }
  435.    
  436.  
  437.  
  438.  
  439. /** SPH_setViewRepresentation
  440. **/
  441. void 
  442. SPH_setViewRepresentation 
  443.    (int viewIndex,
  444.     matrix vo_matrix, matrix vm_matrix,
  445.     double vp_minx, double vp_maxx, 
  446.     double vp_miny, double vp_maxy,
  447.     double vp_minz, double vp_maxz)
  448. {
  449.    srgp__rectangle oldpdcviewport;
  450.    MAT3hvec testvec = {0.0, 0.0, 0.0, 1.0}, resultvec;
  451.    matrix inverse_vm_matrix;
  452.  
  453.  
  454.    SPH_check_system_state;
  455.    SPH_check_no_open_structure;
  456.    SPH_check_view_index;
  457.  
  458.    SPH_check_rectangle (vp_minx,vp_miny,vp_maxx,vp_maxy);
  459.  
  460.    oldpdcviewport = THE_VIEW.pdc_viewport;
  461.    THE_VIEW.viewport = 
  462.       SPH_defNDCrectangle (vp_minx, vp_miny, vp_maxx, vp_maxy);
  463.               
  464.    MAT3copy (THE_VIEW.vo_matrix,   vo_matrix);
  465.    MAT3copy (THE_VIEW.vm_matrix,   vm_matrix);
  466.    
  467.    MAT3invert (inverse_vm_matrix,  vm_matrix);
  468.    
  469.    MAT3mult_hvec (resultvec, testvec, inverse_vm_matrix, TRUE);
  470.    THE_VIEW.frontPlaneDistance = resultvec[Z];
  471.   
  472. #ifdef DEBUG
  473.    fprintf (stderr, "Backcalcing the F from z=0 results in %f\n", resultvec[Z]);
  474. #endif
  475.  
  476.    testvec[Z] = 1.0;
  477.    MAT3mult_hvec (resultvec, testvec, inverse_vm_matrix, TRUE);
  478.    THE_VIEW.backPlaneDistance = resultvec[Z];
  479.    
  480. #ifdef DEBUG
  481.    fprintf (stderr, "Backcalcing the B from z=1 results in %f\n", resultvec[Z]);
  482. #endif
  483.  
  484.    if (THE_VIEW.frontPlaneDistance <= THE_VIEW.backPlaneDistance) {
  485.       /**** WHOA!  Bad news!  Can't backcalc (happens in ORTHO matrices) ***/
  486.       /* We'll have to take a not-so-wild guess. */
  487.       THE_VIEW.frontPlaneDistance = most_recent_F;
  488.       THE_VIEW.backPlaneDistance = most_recent_B;
  489.    }
  490.  
  491.    SPH__updateViewInfo (viewIndex);
  492.    SPH__refresh_viewport_change (viewIndex, oldpdcviewport);
  493.  
  494. }
  495.  
  496.  
  497.  
  498.  
  499. void
  500. SPH_setViewPointLightSource (int viewIndex, double u, double v, double n)
  501. {
  502.    MAT3_SET_VEC (THE_VIEW.uvn_point_light_source,
  503.          u,v,n);
  504.    SPH_regenerateScreen();
  505. }
  506.